home *** CD-ROM | disk | FTP | other *** search
/ Aminet 23 / Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso / Aminet / misc / emu / amiSPIMsrc.lha / spim-utils.c < prev    next >
C/C++ Source or Header  |  1994-02-03  |  14KB  |  716 lines

  1. /* SPIM S20 MIPS simulator.
  2.    Misc. routines for SPIM.
  3.    Copyright (C) 1990-1994 by James Larus (larus@cs.wisc.edu).
  4.    ALL RIGHTS RESERVED.
  5.  
  6.    SPIM is distributed under the following conditions:
  7.  
  8.      You may make copies of SPIM for your own use and modify those copies.
  9.  
  10.      All copies of SPIM must retain my name and copyright notice.
  11.  
  12.      You may not sell SPIM or distributed SPIM in conjunction with a
  13.      commerical product or service without the expressed written consent of
  14.      James Larus.
  15.  
  16.    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19.    PURPOSE. */
  20.  
  21.  
  22. /* $Header: /home/primost/larus/Software/SPIM/RCS/spim-utils.c,v 3.38 1994/01/18 03:21:45 larus Exp larus $
  23. */
  24.  
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #ifdef __STDC__
  30. #include <stdarg.h>
  31. #else
  32. #include <varargs.h>
  33. #endif
  34.  
  35. #include "spim.h"
  36. #include "spim-utils.h"
  37. #include "inst.h"
  38. #include "data.h"
  39. #include "mem.h"
  40. #include "reg.h"
  41. #include "scanner.h"
  42. #include "parser.h"
  43. #include "y.tab.h"
  44. #include "run.h"
  45. #include "sym-tbl.h"
  46.  
  47. #ifdef CL_SPIM
  48. #include "cl-cache.h"
  49. #include "cl-cycle.h"
  50. #include "cl-tlb.h"
  51. #include "cl-except.h"
  52. #endif
  53.  
  54.  
  55. /* Internal functions: */
  56.  
  57. #ifdef __STDC__
  58. static mem_addr copy_int_to_stack (int n);
  59. static mem_addr copy_str_to_stack (char *s);
  60. static void delete_all_breakpoints (void);
  61. #else
  62. static mem_addr copy_int_to_stack ();
  63. static mem_addr copy_str_to_stack ();
  64. static void delete_all_breakpoints ();
  65. #endif
  66.  
  67.  
  68. /* Global Variables: */
  69.  
  70. int bare_machine = 0;        /* Non-zero => ignore assembler
  71.                    embellishments to bare hardware */
  72.  
  73. int quiet = 0;            /* Non-zero => no message on traps. */
  74.  
  75.  
  76. int message_out = 0, console_out = 0;
  77.  
  78. mem_addr program_starting_address = 0;
  79.  
  80. long initial_text_size = TEXT_SIZE;
  81.  
  82. long initial_data_size = DATA_SIZE;
  83.  
  84. long initial_data_limit = DATA_LIMIT;
  85.  
  86. long initial_stack_size = STACK_SIZE;
  87.  
  88. long initial_stack_limit = STACK_LIMIT;
  89.  
  90. long initial_k_text_size = K_TEXT_SIZE;
  91.  
  92. long initial_k_data_size = K_DATA_SIZE;
  93.  
  94. long initial_k_data_limit = K_DATA_LIMIT;
  95.  
  96.  
  97.  
  98. /* Initialize or reinitialize the state of the machine. */
  99.  
  100. #ifdef __STDC__
  101. void
  102. initialize_world (int load_trap_handler)
  103. #else
  104. void
  105. initialize_world (load_trap_handler)
  106.      int load_trap_handler;
  107. #endif
  108. {
  109.   /* Allocate the floating point registers */
  110.   if (FGR == NULL)
  111.     FPR = (double *) xmalloc (16 * sizeof (double));
  112.   /* Allocate the memory */
  113.   make_memory (initial_text_size,
  114.            initial_data_size, initial_data_limit,
  115.            initial_stack_size, initial_stack_limit,
  116.            initial_k_text_size,
  117.            initial_k_data_size, initial_k_data_limit);
  118.   initialize_registers ();
  119.   initialize_symbol_table ();
  120.   k_text_begins_at_point (K_TEXT_BOT);
  121.   k_data_begins_at_point (K_DATA_BOT);
  122.   data_begins_at_point (DATA_BOT);
  123.   text_begins_at_point (TEXT_BOT);
  124.   if (load_trap_handler)
  125.     {
  126.       int old_bare = bare_machine;
  127.  
  128.       bare_machine = 0;        /* Trap handler uses extended machine */
  129.       if (read_assembly_file (DEFAULT_TRAP_HANDLER))
  130.     fatal_error ("Cannot read trap handler: %s\n", DEFAULT_TRAP_HANDLER);
  131.       bare_machine = old_bare;
  132.       write_output (message_out, "Loaded: %s\n", DEFAULT_TRAP_HANDLER);
  133.     }
  134.   initialize_scanner (stdin);
  135.   delete_all_breakpoints ();
  136. #ifdef CL_SPIM
  137.   /* cycle level stuff */
  138.   mem_system = mem_sys_init ();
  139.   cycle_running = 0;
  140. #endif
  141. }
  142.  
  143.  
  144. #ifdef __STDC__
  145. void
  146. write_startup_message (void)
  147. #else
  148. void
  149. write_startup_message ()
  150. #endif
  151. {
  152. #ifdef CL_SPIM
  153.   write_output (message_out, "CL-SPIM %s\n", SPIM_VERSION);
  154.   write_output (message_out,
  155.         "Copyright 1990-1994 by James R. Larus (larus@cs.wisc.edu).\n");
  156.   write_output (message_out,
  157.         "Copyright (C) 1991-1994 by Anne Rogers (amr@cs.princeton.edu)\n");
  158.   write_output (message_out,
  159.         "and Scott Rosenberg (scottr@cs.princeton.edu).\n");
  160. #else
  161.   write_output (message_out, "SPIM %s\n", SPIM_VERSION);
  162.   write_output (message_out,
  163.         "Copyright 1990-1994 by James R. Larus (larus@cs.wisc.edu).\n");
  164. #endif
  165.   write_output (message_out, "All Rights Reserved.\n");
  166.   write_output (message_out, "See the file README a full copyright notice.\n");
  167. }
  168.  
  169.  
  170.  
  171. #ifdef __STDC__
  172. void
  173. initialize_registers (void)
  174. #else
  175. void
  176. initialize_registers ()
  177. #endif
  178. {
  179.   bzero (FPR, 16 * sizeof (double));
  180.   FGR = (float *) FPR;
  181.   FWR = (int *) FPR;
  182.   bzero (R, 32 * sizeof (reg_word));
  183.   R[29] = STACK_TOP - BYTES_PER_WORD - 4096; /* Initialize $sp */
  184.   PC = 0;
  185.   Cause = 0;
  186.   EPC = 0;
  187.   Status_Reg = 0;
  188.   BadVAddr = 0;
  189.   Context = 0;
  190.   PRId = 0;
  191. #ifdef CL_SPIM
  192.   PC = 0;
  193.   Status_Reg = (0x3 << 28) | (0x3);
  194. #endif
  195. }
  196.  
  197.  
  198. /* Read file NAME, which should contain assembly code. Return zero if
  199.    successful and non-zero otherwise. */
  200.  
  201. #ifdef __STDC__
  202. int
  203. read_assembly_file (char *name)
  204. #else
  205. int
  206. read_assembly_file (name)
  207.      char *name;
  208. #endif
  209. {
  210.   FILE *file = fopen (name, "r");;
  211.  
  212.   source_file = 1;
  213.   if (file == NULL)
  214.     {
  215.       error ("Cannot open file: `%s'\n", name);
  216.       return (1);
  217.     }
  218.   else
  219.     {
  220. #ifdef mips
  221. #include <sys/exec.h>
  222.       unsigned short magic;
  223.  
  224.       fread (&magic, sizeof (short), 1, file);
  225.       fclose (file);
  226.       if (magic == MIPSEBMAGIC || magic == MIPSELMAGIC)
  227.     {
  228.       error ("Source file appears to be executable: %s\n", name);
  229.       return (1);
  230.     }
  231.       fopen (name, "r");
  232. #endif
  233.       initialize_scanner (file);
  234.       initialize_parser (name);
  235.       while (!yyparse ()) ;
  236.       fclose (file);
  237.       flush_local_labels ();
  238.       end_of_assembly_file ();
  239.       return (0);
  240.     }
  241. }
  242.  
  243.  
  244. #ifdef __STDC__
  245. mem_addr
  246. starting_address (void)
  247. #else
  248. mem_addr
  249. starting_address ()
  250. #endif
  251. {
  252.   if (PC == 0)
  253.     {
  254.       if (program_starting_address)
  255.     return (program_starting_address);
  256.       else
  257.     return (program_starting_address
  258.         = find_symbol_address (DEFAULT_RUN_LOCATION));
  259.     }
  260.   else
  261.     return (PC);
  262. }
  263.  
  264.  
  265. /* Initialize the SPIM stack with ARGC, ARGV, and ENVP data. */
  266.  
  267. #ifdef __STDC__
  268. void
  269. initialize_run_stack (int argc, char **argv)
  270. #else
  271. void
  272. initialize_run_stack (argc, argv)
  273.      int argc;
  274.      char **argv;
  275. #endif
  276. {
  277.   char **p;
  278.   extern char **environ;
  279.   int i, j = 0, env_j;
  280.   mem_addr addrs[10000];
  281.  
  282.   R[REG_A2] = R[29];
  283.  
  284.   /* Put strings on stack: */
  285.   for (p = environ; *p != '\0'; p++)
  286.     addrs[j++] = copy_str_to_stack (*p);
  287.  
  288.   R[REG_A1] = R[29];
  289.   env_j = j;
  290.   for (i = 0; i < argc; i++)
  291.     addrs[j++] = copy_str_to_stack (argv[i]);
  292.  
  293.   R[29] = (R[29] - 7) & ~7;    /* Double-word align */
  294.   /* Build vectors on stack: */
  295.   for (i = env_j - 1; i >= 0; i--)
  296.     copy_int_to_stack (addrs[i]);
  297.   for (i = j - 1; i >= env_j; i--)
  298.     copy_int_to_stack (addrs[i]);
  299.  
  300.   R[REG_A0] = argc;
  301.   R[29] = R[29] & ~7;        /* Round down to nearest double-word */
  302.   R[29] = copy_int_to_stack (argc); /* Leave pointing to argc */
  303.  
  304. }
  305.  
  306.  
  307. #ifdef __STDC__
  308. static mem_addr
  309. copy_str_to_stack (char *s)
  310. #else
  311. static mem_addr
  312. copy_str_to_stack (s)
  313.      char *s;
  314. #endif
  315. {
  316.   mem_addr str_start;
  317.   int i = strlen (s);
  318.  
  319.   while (i >= 0)
  320.     {
  321.       SET_MEM_BYTE (R[29], s[i]);
  322.       R[29] -= 1;
  323.       i -= 1;
  324.     }
  325.   str_start = (mem_addr) R[29] + 1;
  326.   R[29] = R[29] & 0xfffffffc;    /* Round down to word boundary */
  327.   return (str_start);
  328. }
  329.  
  330.  
  331. #ifdef __STDC__
  332. static mem_addr
  333. copy_int_to_stack (int n)
  334. #else
  335. static mem_addr
  336. copy_int_to_stack (n)
  337.      int n;
  338. #endif
  339. {
  340.   SET_MEM_WORD (R[29], n);
  341.   R[29] -= BYTES_PER_WORD;
  342.   return ((mem_addr) R[29] + BYTES_PER_WORD);
  343. }
  344.  
  345.  
  346. /* Run a program starting at PC for N steps and display each
  347.    instruction before executing if FLAG is non-zero.  If CONTINUE is
  348.    non-zero, then step through a breakpoint.  Return non-zero if
  349.    breakpoint is encountered. */
  350.  
  351. #ifdef __STDC__
  352. int
  353. run_program (mem_addr pc, int steps, int display, int cont_bkpt)
  354. #else
  355. int
  356. run_program (pc, steps, display, cont_bkpt)
  357.      mem_addr pc;
  358.      int steps, display, cont_bkpt;
  359. #endif
  360. {
  361.   if (cont_bkpt && inst_is_breakpoint (pc))
  362.     {
  363.       mem_addr addr = PC == 0 ? pc : PC;
  364.  
  365.       delete_breakpoint (addr);
  366.       exception_occurred = 0;
  367.       run_spim (addr, 1, display);
  368.       add_breakpoint (addr);
  369.       steps -= 1;
  370.       pc = PC;
  371.     }
  372.  
  373.   exception_occurred = 0;
  374.   if (!run_spim (pc, steps, display))
  375.     /* Can't restart program */
  376.     PC = 0;
  377.   if (exception_occurred && Cause == (BKPT_EXCPT << 2))
  378.     return (1);
  379.   else
  380.     return (0);
  381. }
  382.  
  383.  
  384. /* Record of where a breakpoint was placed and the instruction previously
  385.    in memory. */
  386.  
  387. typedef struct bkptrec
  388. {
  389.   mem_addr addr;
  390.   instruction *inst;
  391.   struct bkptrec *next;
  392. } bkpt;
  393.  
  394.  
  395. static bkpt *bkpts = NULL;
  396.  
  397.  
  398. /* Set a breakpoint at memory location ADDR. */
  399.  
  400. #ifdef __STDC__
  401. void
  402. add_breakpoint (mem_addr addr)
  403. #else
  404. void
  405. add_breakpoint (addr)
  406.      mem_addr addr;
  407. #endif
  408. {
  409.   bkpt *rec = (bkpt *) xmalloc (sizeof (bkpt));
  410.  
  411.   rec->next = bkpts;
  412.   rec->addr = addr;
  413.  
  414.   if ((rec->inst = set_breakpoint (addr)) != NULL)
  415.     bkpts = rec;
  416.   else
  417.     {
  418.       if (exception_occurred)
  419.     error ("Cannot put a breakpoint at address 0x%08x\n", addr);
  420.       else
  421.     error ("No instruction to breakpoint at address 0x%08x\n", addr);
  422.       free (rec);
  423.     }
  424. }
  425.  
  426.  
  427. /* Delete all breakpoints at memory location ADDR. */
  428.  
  429. #ifdef __STDC__
  430. void
  431. delete_breakpoint (mem_addr addr)
  432. #else
  433. void
  434. delete_breakpoint (addr)
  435.      mem_addr addr;
  436. #endif
  437. {
  438.   bkpt *p, *b;
  439.   int deleted_one = 0;
  440.  
  441.   for (p = NULL, b = bkpts; b != NULL; )
  442.     if (b->addr == addr)
  443.       {
  444.     bkpt *n;
  445.  
  446.     SET_MEM_INST (addr, b->inst);
  447.     if (p == NULL)
  448.       bkpts = b->next;
  449.     else
  450.       p->next = b->next;
  451.     n = b->next;
  452.     free (b);
  453.     b = n;
  454.     deleted_one = 1;
  455.       }
  456.     else
  457.       p = b, b = b->next;
  458.   if (!deleted_one)
  459.     error ("No breakpoint to delete at 0x%08x\n", addr);
  460. }
  461.  
  462.  
  463. #ifdef __STDC__
  464. static void
  465. delete_all_breakpoints (void)
  466. #else
  467. static void
  468. delete_all_breakpoints ()
  469. #endif
  470. {
  471.   bkpt *b, *n;
  472.  
  473.   for (b = bkpts, n = NULL; b != NULL; b = n)
  474.     {
  475.       n = b->next;
  476.       free (b);
  477.     }
  478.   bkpts = NULL;
  479. }
  480.  
  481.  
  482. /* List all breakpoints. */
  483.  
  484. #ifdef __STDC__
  485. void
  486. list_breakpoints (void)
  487. #else
  488. void
  489. list_breakpoints ()
  490. #endif
  491. {
  492.   bkpt *b;
  493.  
  494.   if (bkpts)
  495.     for (b = bkpts;  b != NULL; b = b->next)
  496.       write_output (message_out, "Breakpoint at 0x%08x\n", b->addr);
  497.   else
  498.     write_output (message_out, "No breakpoints set\n");
  499. }
  500.  
  501.  
  502.  
  503. /* Utility routines */
  504.  
  505. /* Print the error message then exit. */
  506.  
  507. /*VARARGS0*/
  508. #ifdef __STDC__
  509. void
  510. fatal_error (char *fmt, ...)
  511. #else
  512. void
  513. fatal_error (va_alist)
  514. va_dcl
  515. #endif
  516. {
  517.   va_list args;
  518. #ifdef __STDC__
  519.   va_start (args, fmt);
  520. #else
  521.   char *fmt;
  522.  
  523.   va_start (args);
  524. #endif
  525.   fmt = va_arg (args, char *);
  526.  
  527. #if defined(mips) || defined(amiga)
  528.   vfprintf (stderr, fmt, args);
  529. #else
  530.   _doprnt (fmt, args, stderr);
  531. #endif
  532.   exit (-1);
  533.   /*NOTREACHED*/
  534. }
  535.  
  536.  
  537. /* Return the entry in the hash TABLE of length LENGTH with key STRING.
  538.    Return NULL if no such entry exists. */
  539.  
  540. #ifdef __STDC__
  541. inst_info *
  542. map_string_to_inst_info (inst_info tbl[], int tbl_len, char *id)
  543. #else
  544. inst_info *
  545. map_string_to_inst_info (tbl, tbl_len, id)
  546.      register inst_info tbl [];
  547.      int tbl_len;
  548.      register char *id;
  549. #endif
  550. {
  551.   register int low = 0;
  552.   register int hi = tbl_len - 1;
  553.  
  554.   while (low <= hi)
  555.     {
  556.       register int mid = (low + hi) / 2;
  557.       register char *idp = id, *np = tbl[mid].name;
  558.  
  559.       while (*idp == *np && *idp != '\0') {idp ++; np ++;}
  560.  
  561.       if (*np == '\0' && *idp == '\0') /* End of both strings */
  562.     return (& tbl[mid]);
  563.       else if (*idp > *np)
  564.     low = mid + 1;
  565.       else
  566.     hi = mid - 1;
  567.     }
  568.  
  569.   return NULL;
  570. }
  571.  
  572.  
  573. /* Return the entry in the hash TABLE of length LENGTH with VALUE1 field NUM.
  574.    Return NULL if no such entry exists. */
  575.  
  576. #ifdef __STDC__
  577. inst_info *
  578. map_int_to_inst_info (inst_info tbl[], int tbl_len, int num)
  579. #else
  580. inst_info *
  581. map_int_to_inst_info (tbl, tbl_len, num)
  582.      register inst_info tbl [];
  583.      int tbl_len;
  584.      register int num;
  585. #endif
  586. {
  587.   register int low = 0;
  588.   register int hi = tbl_len - 1;
  589.  
  590.   while (low <= hi)
  591.     {
  592.       register int mid = (low + hi) / 2;
  593.  
  594.       if (tbl[mid].value1 == num)
  595.     return (&tbl[mid]);
  596.       else if (num > tbl[mid].value1)
  597.     low = mid + 1;
  598.       else
  599.     hi = mid - 1;
  600.     }
  601.  
  602.   return NULL;
  603. }
  604.  
  605.  
  606. #ifdef NEED_VSPRINTF
  607. char *
  608. vsprintf (str, fmt, args)
  609.      char *str, *fmt;
  610.      va_list *args;
  611. {
  612.   FILE _strbuf;
  613.  
  614.   _strbuf._flag = _IOWRT+_IOSTRG;
  615.   _strbuf._ptr = str;
  616.   _strbuf._cnt = 32767;
  617.   _doprnt(fmt, args, &_strbuf);
  618.   putc('\0', &_strbuf);
  619.   return(str);
  620. }
  621. #endif
  622.  
  623.  
  624. #ifdef NEED_STRTOL
  625. long
  626. strtol (str, eptr, base)
  627.      char *str, *eptr;
  628.      int base;
  629. {
  630.   long result;
  631.  
  632.   if (base != 16)
  633.     fatal_error ("SPIM's strtol only works for base 16 (not base %d)\n", base);
  634.   if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
  635.     str += 2;
  636.   sscanf (str, "%lx", &result);
  637.   return (result);
  638. }
  639.  
  640.  
  641. unsigned long
  642. strtoul (str, eptr, base)
  643.      char *str, *eptr;
  644.      int base;
  645. {
  646.   unsigned long result;
  647.  
  648.   if (base != 16)
  649.     fatal_error ("SPIM's strtoul only works for base 16 (not base %d)\n",
  650.          base);
  651.   if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
  652.     str += 2;
  653.   sscanf (str, "%lx", &result);
  654.   return (result);
  655. }
  656. #endif
  657.  
  658.  
  659. #ifdef __STDC__
  660. char *
  661. str_copy (char *str)
  662. #else
  663. char *
  664. str_copy (str)
  665.      char *str;
  666. #endif
  667. {
  668.   return (strcpy (xmalloc (strlen (str) + 1), str));
  669. }
  670.  
  671.  
  672. #ifdef __STDC__
  673. void *
  674. xmalloc (int size)
  675. #else
  676. char *
  677. xmalloc (size)
  678. int size;
  679. #endif
  680. {
  681. #ifdef __STDC__
  682.   void *x = (void *) malloc (size);
  683. #else
  684.   char *x = (char *) malloc (size);
  685. #endif
  686.  
  687.   if (x == 0)
  688.     fatal_error ("Out of memory at request for %d bytes.\n");
  689.   return (x);
  690. }
  691.  
  692.  
  693. /* Allocate a zero'ed block of storage. */
  694.  
  695. #ifdef __STDC__
  696. void *
  697. zmalloc (int size)
  698. #else
  699. char *
  700. zmalloc (size)
  701. int size;
  702. #endif
  703. {
  704. #ifdef __STDC__
  705.   void *z = (void *) malloc (size);
  706. #else
  707.   char *z = (char *) malloc (size);
  708. #endif
  709.  
  710.   if (z == 0)
  711.     fatal_error ("Out of memory at request for %d bytes.\n");
  712.  
  713.   bzero (z, size);
  714.   return (z);
  715. }
  716.